import { Toast, checkLoginAndNavigate } from '@/utils/util';
import type { ResponseData } from './data';
import { fetchRefreshToken } from './util';

/**
 * Request封装处理
 */
// resolve和reject不返回任何值，但通知promise更改状态
export const handleResponse = <T>(props: {
  res: any;
  resolve: (value: ResponseData<T> | PromiseLike<ResponseData<T>>) => void;
  reject: (reason?: any) => void;
  url?: string;
  isFile?: boolean; // 返回的是流文件
}) => {
  const { res, resolve, reject, url, isFile } = props;
  // 分离了验证状态码逻辑
  if (isSuccessStatusCode(res.statusCode)) {
    if (!!isFile) {
      // 直接返回流文件
      resolve(res);
    } else {
      if (res.data.code == 0) {
        resolve(res.data);
      } else if (res.data.code == 401) {
        // 获取刷新令牌
        const refreshToken = uni.getStorageSync('auth')?.refreshToken;
        // 不存在 refreshToken 则直接跳转登录 或者 是刷新令牌的接口出现401，直接抛出错误信息
        if (!refreshToken || ['/member/auth/refresh-token'].includes(url || '')) {
          // 登录失败
          uni.removeStorageSync('auth');
          // 使用统一的登录检查函数，避免重复跳转
          checkLoginAndNavigate();
          reject(res);
        } else {
          // 刷新token
          fetchRefreshToken(refreshToken);
        }
      } else {
        showErrorToast(res.data);
        reject(res);
      }
    }
  } else {
    // 分离了报错状态码逻辑
    showErrorToast(res.data);
    reject(res);
  }
};

export const handleError = (err: any, reject: (reason?: any) => void) => {
  Toast('网络可能开小差了~');
  reject(err);
};

const isSuccessStatusCode = (statusCode: number) => {
  return statusCode >= 200 && statusCode < 300;
};

const showErrorToast = <T>(data: ResponseData<T>) => {
  Toast(data.msg || '请求错误');
};

const request = <T>(
  url: string,
  method: 'GET' | 'POST' | 'PUT' | 'DELETE',
  data?: Record<string, any>,
  isFile?: boolean
): Promise<ResponseData<T>> => {
  return new Promise((resolve, reject) => {
    uni.request({
      url: process.env.VUE_APP_BASEHOST + url,
      header: {
        Authorization: uni.getStorageSync('auth')?.accessToken,
      },
      responseType: !!isFile ? 'arraybuffer' : undefined,
      method,
      data,
      success: res => {
        // 成功响应
        handleResponse({ res, resolve, reject, url, isFile });
      },
      fail: err => {
        handleError(err, reject);
      },
    });
  });
};

export default request;
